package org.dt.common.sequence.spring;

import org.dt.common.sequence.config.SeqHolderSpec;
import org.dt.common.sequence.config.SeqHolderType;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/**
 * 开启序列号生成
 * <p>
 * 如何使用:
 * 1）在自己的业务库中建立sequence表，表名和字段名可以自己定义。示例如下：
 * CREATE TABLE `t_agr_sequence`
 * (
 * `id`           bigint(20)   NOT NULL AUTO_INCREMENT COMMENT '主键',
 * `agr_biz_code` varchar(64)           DEFAULT NULL COMMENT '业务代码',
 * `max_id`       bigint(20)   NOT NULL COMMENT '当前分配的最大ID',
 * `description`  varchar(256)          DEFAULT NULL COMMENT '描述',
 * <p>
 * `gmt_create`   timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
 * `gmt_modified` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '修改时间',
 * `is_valid`     tinyint(4)            DEFAULT NULL COMMENT '有效标识',
 * `tenant_code`  varchar(20)           DEFAULT NULL COMMENT '租户代码',
 * PRIMARY KEY (`id`),
 * UNIQUE KEY `t_agr_sequence_biz_uindex` (`agr_biz_code`)
 * );
 * <p>
 * 2）配置业务的Spring Configuration，继承{@link BaseSeqManagerConfiguration}，默认需要在其中配置Mybatis Mapper和SequenceHolder，
 * 一个biz对应一个SequenceHolder，在你的Component中注入 {@link org.dt.common.sequence.SequenceHolder}即可。
 * 你也可以覆盖父类的配置。
 * Mybatis Mapper可以参考policy-core的{@code cn.com.cathayins.policy.core.dal.sequence.PolicyCasSeqMapper}，相关的Mapper已经附在下方
 * <p>
 * 3）主启动类上加上 {@link EnableSequenceManager}，参数是你的Spring Configuration
 * <p>
 * 4）在配置文件中添加配置项，示例如下：
 * cathay.sequence.biz.{biz-name}.type=head_spinning
 * cathay.sequence.biz.{biz-name}.spec=capacity=5000,loadFactor=0.5
 * type可配置项为 {@link SeqHolderType*
 * spec可配置项为 {@link SeqHolderSpec}
 *
 * @author: yujiadong
 * @create: 2019/01/11 11:20
 **/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(SeqManagerInitializationConfiguration.class)
public @interface EnableSequenceManager {

    Class<? extends BaseSeqManagerConfiguration> configuration();

}

/*public interface PolicyBaseSeqMapper extends BaseSeqMapper {
    @Override
    @Select("select 1 from t_agr_sequence where agr_biz_code=#{biz}")
    Integer checkBizItemExists(@Param("biz") String biz);
    
    @Override
    @Insert("INSERT INTO t_agr_sequence (agr_biz_code, max_id, `description`) VALUES (#{biz}, #{firstId}, #{desc})")
    int insert(@Param("biz") String biz, @Param("firstId") Integer firstId, @Param("desc") String desc);
    
    @Override
    @Select("select max_id from t_agr_sequence where agr_biz_code=#{biz}")
    long queryMaxId(@Param("biz") String biz);
}*/

/*public interface PolicyCasSeqMapper extends PolicyBaseSeqMapper, CasSeqMapper {
    //how to lock row after where clause finished -> stackoverflow
    //we can't do this
    @Update({"update t_agr_sequence set max_id=#{maxIdActual} where agr_biz_code=#{biz} and max_id=#{maxIdExcepted}"})
    @Override
    int updateMaxId(@Param("biz") String biz, @Param("maxIdExcepted") Long maxIdExcepted, @Param("maxIdActual") Long maxIdActual);
}*/

/*@Configuration
@MapperScan(basePackageClasses = {PolicyCasSeqMapper.class})
public class PolicySeqManagerConfiguration extends BaseSeqManagerConfiguration {
    
    @Override
    @Bean
    public CasDelegator delegator(CasSeqMapper mapper) {
        Validate.notNull(mapper);
        return new CasDelegator(mapper);
    }
    
    @Bean("policySequenceHolder")
    @Override
    public SequenceHolder sequenceHolder(SequenceHolderFactory sequenceHolderFactory) {
        return sequenceHolderFactory.sequenceHolder("sequence");
    }
    
    @Bean("endorsementSequenceHolder")
    public SequenceHolder sequenceHolder1(SequenceHolderFactory sequenceHolderFactory) {
        return sequenceHolderFactory.sequenceHolder("endorsement");
    }
    
}*/

/*public interface PolicyTransactionSeqMapper extends PolicyBaseSeqMapper, TransactionSeqMapper {
    
    @Override
    @Select("select max_id+1 as lower_bound,max_id+#{step} as upper_bound from t_agr_sequence where agr_biz_code=#{biz}")
    Sequence getNextSequence(@Param("biz") String biz, @Param("step") long step);
    
    @Override
    @Update({"update t_agr_sequence set max_id=max_id+#{step} where agr_biz_code=#{biz}"})
    int updateMaxId(@Param("biz") String biz, @Param("step") long step);
}*/
